package models

import (
	"errors"

	"gorm.io/gorm"
)

type SysAuthority struct {
	CreatedAt       XTime          `json:"createTime"` // 创建时间
	UpdatedAt       XTime          `json:"updateTime"` // 更新时间
	DeletedAt       *XTime         `sql:"index"`
	AuthorityId     uint           `json:"authorityId" gorm:"not null;unique;primary_key;comment:角色ID;size:90"` // 角色ID
	AuthorityName   string         `json:"authorityName" gorm:"comment:角色名"`
	ParentId        uint           `json:"parentId" gorm:"comment:父角色ID" form:"parentId"` // 父角色ID
	DataAuthorityId []SysAuthority `json:"dataAuthorityId" gorm:"many2many:sys_data_authority_id"`
	Children        []SysAuthority `json:"children" gorm:"-"`
	SysBaseMenus    []SysBaseMenu  `json:"menus" gorm:"many2many:sys_authority_menus;"`
	Users           []SysUser      `json:"-" gorm:"many2many:sys_user_authority;"`
	DefaultRouter   string         `json:"defaultRouter" gorm:"comment:默认菜单;default:dashboard"` // 默认菜单(默认dashboard)
}

//@function: CreateAuthority
//@description: 创建一个角色
//@param: auth model.SysAuthority
//@return: err error, authority model.SysAuthority
func CreateAuthority(auth SysAuthority) (err error, authority SysAuthority) {
	var authorityBox SysAuthority
	if !errors.Is(db.Where("authority_id = ?", auth.AuthorityId).First(&authorityBox).Error, gorm.ErrRecordNotFound) {
		return errors.New("已经存在相同角色id"), auth
	}

	err = db.Create(&auth).Error
	return err, auth
}

//@function: UpdateAuthority
//@description: 更改一个角色
//@param: auth model.SysAuthority
//@return:err error, authority model.SysAuthority
func UpdateAuthority(auth SysAuthority, pid int) (err error, authority SysAuthority) {
	err = db.Where("authority_id = ?", pid).First(&SysAuthority{}).Updates(&auth).Error
	return err, auth
}

//@function: DeleteAuthority
//@description: 删除角色
//@param: auth *model.SysAuthority
//@return: err error

func DeleteAuthority(auth *SysAuthority, id int) (err error) {
	if !errors.Is(db.Where("authority_id = ?", id).First(&SysUser{}).Error, gorm.ErrRecordNotFound) {
		return errors.New("此角色有用户正在使用禁止删除")
	}
	if !errors.Is(db.Where("parent_id = ?", id).First(&SysAuthority{}).Error, gorm.ErrRecordNotFound) {
		return errors.New("此角色存在子角色不允许删除")
	}
	db := db.Where("authority_id = ?", id).First(auth)
	err = db.Unscoped().Delete(auth).Error
	if err != nil {
		return err
	}
	if len(auth.SysBaseMenus) > 0 {
		err = db.Model(auth).Association("SysBaseMenus").Delete(auth.SysBaseMenus)
		err = db.Association("SysBaseMenus").Delete(&auth)
	}
	// ClearCasbin(0, auth.AuthorityId)
	return err
}

//@function: GetAuthorityInfoList
//@description: 分页获取数据
//@param: info request.PageInfo
//@return: err error, list interface{}, total int64

func GetAuthorityInfoList(page, pageSize int) (err error, list interface{}, total int64) {
	limit := pageSize
	offset := pageSize * (page - 1)
	var authority []SysAuthority
	err = db.Preload("SysBaseMenus").Limit(limit).Offset(offset).Where("parent_id = 0").Find(&authority).Error
	err = db.Model(&SysAuthority{}).Where("parent_id = 0").Count(&total).Error
	if len(authority) > 0 {
		for k := range authority {
			err = findChildrenAuthority(&authority[k])
		}
	}
	return err, authority, total
}

//@function: findChildrenAuthority
//@description: 查询子角色
//@param: authority *model.SysAuthority
//@return: err error

func findChildrenAuthority(authority *SysAuthority) (err error) {
	err = db.Preload("SysBaseMenus").Where("parent_id = ?", authority.AuthorityId).Find(&authority.Children).Error
	if len(authority.Children) > 0 {
		for k := range authority.Children {
			err = findChildrenAuthority(&authority.Children[k])
		}
	}
	return err
}

//@function: GetAuthorityInfo
//@description: 获取所有角色信息
//@param: auth model.SysAuthority
//@return: err error, sa model.SysAuthority

func GetAuthorityInfo(authorityId int64) (err error, sa SysAuthority) {
	err = db.Preload("DataAuthorityId").Where("authority_id = ?", authorityId).First(&sa).Error
	return err, sa
}

//@function: SetMenuAuthority
//@description: 菜单与角色绑定
//@param: auth *model.SysAuthority
//@return: error
func SetMenuAuthority(auth *SysAuthority) error {
	var s SysAuthority
	db.Preload("SysBaseMenus").First(&s, "authority_id = ?", auth.AuthorityId)
	err := db.Model(&s).Association("SysBaseMenus").Replace(&auth.SysBaseMenus)
	return err
}
